package masterjava.common.ws;

import com.sun.xml.ws.developer.ValidationErrorHandler;
import masterjava.common.exception.CommonExceptionType;
import masterjava.common.exception.FaultFactory;
import masterjava.common.logging.MasterLogger;
import org.apache.commons.collections.CollectionUtils;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import javax.xml.ws.WebServiceContext;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class ValidationHandler extends ValidationErrorHandler {
    private static final MasterLogger LOGGER = MasterLogger.get(ValidationHandler.class);

    private static final String ERROR_LIST = "ERROR_LIST";
    private List<SAXParseException> errorList = new LinkedList<SAXParseException>();
    private static final Pattern PATTERN_NOT_VALID_ELEMENT = Pattern.compile("element '(.+)' is not valid");

    @Override
    public void warning(SAXParseException exception) throws SAXException {
        LOGGER.warn("Request validation warning: " + exception.toString(), exception);
    }

    @Override
    public void error(SAXParseException exception) throws SAXException {
        errorList.add(exception);
        packet.invocationProperties.put(ERROR_LIST, errorList);
    }

    @Override
    public void fatalError(SAXParseException exception) throws SAXException {
        errorList.add(exception);
        packet.invocationProperties.put(ERROR_LIST, errorList);
    }

    public static List<SAXParseException> getErrorList(WebServiceContext wsContext) {
        return (List<SAXParseException>) wsContext.getMessageContext().get(ERROR_LIST);
    }

    public static String getWrongElement(String msg) {
        Matcher matcher = PATTERN_NOT_VALID_ELEMENT.matcher(msg);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return null;
    }

    public static List<String> getWrongElementList(List<SAXParseException> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            List<String> paramList = new ArrayList<String>(list.size());
            for (SAXParseException e : list) {
                String param = getWrongElement(e.getMessage());
                if (param != null) {
                    paramList.add(param);
                }
            }
            return paramList;
        }
        return null;
    }

    public static void validate(WebServiceContext ctx) throws WebServiceFault {
        List<SAXParseException> list = getErrorList(ctx);
        if (CollectionUtils.isNotEmpty(list)) {
            StringBuilder sb = new StringBuilder();
            for (SAXParseException ex : list) {
                sb.append(ex.getMessage()).append("\n");
            }
            throw FaultFactory.createFault(CommonExceptionType.VALIDATION_ERROR, sb.toString(), getWrongElementList(list));
        }
    }
}
